home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / obj2asm.zip / ODISASM.C < prev    next >
Text File  |  1991-12-20  |  58KB  |  1,965 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "o.h"
  4.  
  5. /*
  6. ** Local Prototypes
  7. */
  8. char *reg_format( int, char *, char *, char *, char * );
  9. int check_getc( dword * );
  10. int check_getw( dword * );
  11. int check_getl( dword * );
  12. int check_getv( dword *, int );
  13. int get_checkc( dword * );
  14. void instr_opcode( char * );
  15. void instr_operand( char * );
  16. int check_forward( INST_T [], int );
  17. int mod0( int, int, char *, char *, uchar, int, int * );
  18. int mod1( int, int, char *, char *, uchar );
  19. int mod2( int, int, char *, char *, uchar, int, int * );
  20. int mod3( int, char *, uchar, int, int * );
  21. int do_sib( char *, uchar * );
  22. int do_mod_rm( char *, uchar, uchar, int, int, int );
  23. int byte_immed( char *, int, int );
  24. int word_immed( char *, int );
  25.  
  26. char    *regs[4][8] = {
  27.       "al",  "cl",  "dl",  "bl",  "ah",  "ch",  "dh",  "bh",
  28.       "ax",  "cx",  "dx",  "bx",  "sp",  "bp" , "si",  "di",
  29.      "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
  30.       "??",  "??",  "??",  "??",  "??",  "??",  "??",  "??"
  31. };
  32.  
  33. char    *sregs [] = { "es" , "cs" , "ss" , "ds" , "fs" , "gs"  };
  34. char    *sregsc[] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
  35.  
  36. char    *cr_regs[] = { "cr0",    "", "cr2", "cr3", "", "",    "",    "" };
  37. char    *dr_regs[] = { "dr0", "dr1", "dr2", "dr3", "", "", "dr6", "dr7" };
  38. char    *tr_regs[] = {    "",    "",    "",    "", "", "", "tr6", "tr7" };
  39.  
  40. char    *addr_mode[] = { "[bx+si", "[bx+di", "[bp+si", "[bp+di",
  41.                             "[si",    "[di",    "[bp",    "[bx" };
  42.  
  43. char    *addr_386m[] = {   "[eax",   "[ecx",   "[edx",   "[ebx",
  44.                            "[esp",   "[ebp",   "[esi",   "[edi" };
  45.  
  46. char    *sib_scale[] = {  "", "*2", "*4", "*8" };
  47.  
  48. char    *op_grp[10][8] = {
  49.      "add",   "or",  "adc",  "sbb",  "and",  "sub",  "xor",  "cmp",
  50.      "rol",  "ror",  "rcl",  "rcr",  "shl",  "shr",     "",  "sar",
  51.     "test",     "",  "not",  "neg",  "mul", "imul",  "div", "idiv",
  52.      "inc",  "dec",     "",     "",     "",     "",     "",     "",
  53.      "inc",  "dec", "call", "call",  "jmp",  "jmp", "push",     "",
  54.     "sldt",  "str", "lldt",  "ltr", "verr", "verw",     "",     "",
  55.     "sgdt", "sidt", "lgdt", "lidt", "smsw",     "", "lmsw",     "",
  56.         "",     "",     "",     "",   "bt",  "bts",  "btr",  "btc",
  57.      "pop",     "",     "",     "",     "",     "",     "",     "",
  58.      "mov",     "",     "",     "",     "",     "",     "",     ""
  59. };
  60.  
  61. char    *sz_text[] = { "byte ptr ", "word ptr ", "dword ptr ",
  62.                        "qword ptr ", "tbyte ptr "              };
  63.  
  64. char *dir_fmt[] = {
  65.     "%s,%s",                    /* 0 = mem,reg */
  66.     "%s,%s",                    /* 1 = reg,mem */
  67.     "%s",                       /* 2 = mem */
  68.     "%s,%s,%s",                 /* 3 = reg,mem,third */
  69.     "%s,%s,%s"                  /* 4 = mem,reg,third */
  70. };
  71.  
  72. typedef struct modrm_s MODRM_CLASS;
  73.  
  74. struct modrm_s {
  75.     int     dir;
  76.     int     size;
  77.     int     method;
  78.     int     group;
  79.     int     size_needed;
  80.     int     type;
  81. };
  82.  
  83.  
  84. /*
  85. ** These mod r/m classes are not in any particular order, but the
  86. ** instruction table indexes these entries with it's mod_rm_type field.
  87. */
  88. MODRM_CLASS modrm_class[] = {
  89.     0,  0,  1,  0,  FALSE,  UNKNOWN,    /*  0 Math instructions (byte) M,reg */
  90.     0,  1,  1,  0,  FALSE,  UNKNOWN,    /*  1 Math instructions (word) M,reg (and ARPL) */
  91.     1,  0,  1,  0,  FALSE,  UNKNOWN,    /*  2 Math instructions (byte) reg,M */
  92.     1,  1,  1,  0,  FALSE,  UNKNOWN,    /*  3 Math instructions (word) reg,M */
  93.     0,  0,  5,  1,  TRUE,   UNKNOWN,    /*  4 Group 1 (math) byte */
  94.     0,  1,  6,  1,  TRUE,   UNKNOWN,    /*  5 Group 1 (math) word */
  95.     0,  1,  7,  1,  TRUE,   UNKNOWN,    /*  6 Group 1 (math) signed byte */
  96.     0,  1,  2,  0,  TRUE,   UNKNOWN,    /*  7 Segment register unloading */
  97.     1,  1,  2,  0,  TRUE,   UNKNOWN,    /*  8 Segment register loading */
  98.     1,  1,  1,  0,  FALSE,  UNKNOWN,    /*  9 LEA instruction */
  99.     2,  1,  0,  9,  FALSE,  UNKNOWN,    /* 10 POP mod 0 r/m instruction */
  100.     0,  0,  5,  2,  FALSE,  UNKNOWN,    /* 11 Group 2 (rotates) byte */
  101.     0,  1,  5,  2,  FALSE,  UNKNOWN,    /* 12 Group 2 (rotates) word */
  102.     0,  0,  3,  2,  TRUE,   UNKNOWN,    /* 13 Group 2 (rotates) byte by 1 */
  103.     0,  1,  3,  2,  TRUE,   UNKNOWN,    /* 14 Group 2 (rotates) word by 1 */
  104.     0,  0,  4,  2,  TRUE,   UNKNOWN,    /* 15 Group 2 (rotates) byte by CL */
  105.     0,  1,  4,  2,  TRUE,   UNKNOWN,    /* 16 Group 2 (rotates) word by CL */
  106.     1,  2,  1,  0,  FALSE,  UNKNOWN,    /* 17 LES,LDS,BOUND,LSS,LFS,LGS */
  107.     0,  0,  5, 10,  TRUE,   UNKNOWN,    /* 18 Move immediate (byte) */
  108.     0,  1,  6, 10,  TRUE,   UNKNOWN,    /* 19 Move immediate (word) */
  109.     2,  0,  0,  3,  FALSE,  UNKNOWN,    /* 20 Group 3 (special) byte */
  110.     2,  1,  0,  3,  FALSE,  UNKNOWN,    /* 21 Group 3 (special) word */
  111.     2,  0,  0,  4,  TRUE,   UNKNOWN,    /* 22 Group 4 (inc/dec) byte */
  112.     2,  1,  0,  5,  FALSE,  UNKNOWN,    /* 23 Group 5 (special) word/dword */
  113.     3,  1,  8,  0,  FALSE,  UNKNOWN,    /* 24 IMUL (3 parms [reg,mem,immed word]) */
  114.     3,  1,  9,  0,  FALSE,  UNKNOWN,    /* 25 IMUL (3 parms [reg,mem,immed signed byte]) */
  115.     2,  1,  0,  6,  FALSE,  UNKNOWN,    /* 26 Group 6 (special 286/386 instructions) */
  116.     2,  3,  0,  7,  TRUE,   FWORD_PTR,  /* 27 Group 7 (special 286/386 instructions) */
  117.     1,  1,  1,  0,  TRUE,   UNKNOWN,    /* 28 LAR,LSL reg,M (word) */
  118.     0,  0,  5,  8,  TRUE,   BYTE_PTR,   /* 29 Group 8 (386-bit) byte */
  119.     2,  0,  0,  0,  TRUE,   BYTE_PTR,   /* 30 386 Set cc Instructions */
  120.     0,  2, 10,  0,  FALSE,  UNKNOWN,    /* 31 386 Mov r32,crX */
  121.     1,  2, 10,  0,  FALSE,  UNKNOWN,    /* 32 386 Mov crX,r32 */
  122.     0,  2, 11,  0,  FALSE,  UNKNOWN,    /* 33 386 Mov r32,drX */
  123.     1,  2, 11,  0,  FALSE,  UNKNOWN,    /* 34 386 Mov drX,r32 */
  124.     0,  2, 12,  0,  FALSE,  UNKNOWN,    /* 35 386 Mov r32,trX */
  125.     1,  2, 12,  0,  FALSE,  UNKNOWN,    /* 36 386 Mov trX,r32 */
  126.     1,  1,  1,  0,  TRUE,   BYTE_PTR,   /* 37 386 Movsx, Movzx */
  127.     1,  1,  1,  0,  TRUE,   WORD_PTR,   /* 38 386 Movsx, Movzx */
  128.     4,  1,  9,  0,  TRUE,   UNKNOWN,    /* 39 386 Shld,Shrd mem/reg,reg,imm byte */
  129.     4,  1, 13,  0,  TRUE,   UNKNOWN,    /* 40 386 Shld,Shrd mem/reg,reg,cl */
  130. };
  131.  
  132.  
  133. extern int pub_compare();
  134. extern int ext_compare();
  135.  
  136. int over_seg     = -1;      /*   -1  = No overiding segment yet      */
  137.  
  138. static  int over_opsize  = FALSE;   /* FALSE = No overiding operand size yet */
  139. static  int over_adrsize = FALSE;   /* FALSE = No overiding address size yet */
  140. static  int size_large   = FALSE;   /* Within a WORD address size            */
  141. static  int addr_large   = FALSE;   /* Special Addressing Modes              */
  142. static  int size_bytes   = 2;       /* Default WORD size                     */
  143. static  int addr_bytes   = 2;       /* Default WORD size                     */
  144.  
  145. static  char    fp_opcode[8] = {0};     /* 7 + \0 */
  146. static  char    fp_wait = FALSE;        /* No preceeding "wait" */
  147.  
  148. void inst_init()
  149. {
  150.     over_seg     = -1;              /* Setup for the next instruction */
  151.     over_opsize  = FALSE;
  152.     over_adrsize = FALSE;
  153.  
  154.     if ( segment_mode == 386 ) {
  155.         size_large = TRUE;
  156.         addr_large = TRUE;
  157.     } else {
  158.         size_large = FALSE;
  159.         addr_large = FALSE;
  160.     }
  161.     size_bytes = segment_bytes;
  162.     addr_bytes = segment_bytes;
  163. }
  164.  
  165.  
  166. char *reg_format( reg, output_string, base_text, base_fmt, extra_fmt )
  167.     int             reg;
  168.     char            *output_string;
  169.     char            *base_text;
  170.     char            *base_fmt;
  171.     char            *extra_fmt;
  172. {
  173.     if ( reg == NREG ) {
  174.         sprintf( output_string, base_fmt, base_text );
  175.     } else {
  176.         if ( reg < 9 ) {        /* Byte sized half register */
  177.             sprintf( output_string, extra_fmt, base_text, regs[0][reg-1] );
  178.         } else {
  179.             if ( reg < 17 ) {   /* Word/DWord sized general register */
  180.                 if ( size_large ) {
  181.                     sprintf( output_string, extra_fmt, base_text, 
  182.                                                             regs[2][reg-9] );
  183.                 } else {
  184.                     sprintf( output_string, extra_fmt, base_text, 
  185.                                                             regs[1][reg-9] );
  186.                 }
  187.             } else {
  188.                 sprintf( output_string, extra_fmt, base_text, sregs[reg-17] );
  189.             }
  190.         }
  191.     }
  192.     return( output_string );
  193. }
  194.  
  195. int check_getc( result )
  196.     dword   *result;
  197. {
  198.     int             ch;
  199.  
  200.     ch = buff_getc();
  201.  
  202.     if ( ch == EOF ) {
  203.         return( TRUE );
  204.     } else {
  205.         *result = (dword)ch;
  206.         return( FALSE );
  207.     }
  208. }
  209.  
  210. int check_getw( result )
  211.     dword   *result;
  212. {
  213.     int             ch;
  214.  
  215.     ch = buff_getc();
  216.     if ( ch == EOF ) {
  217.         return( TRUE );
  218.     }
  219.     *result = ch;
  220.     ch = buff_getc();
  221.     if ( ch == EOF ) {
  222.         return( TRUE );
  223.     }
  224.     *result += ch << 8;
  225.     return( FALSE );
  226. }
  227.  
  228. int check_getl( result )
  229.     dword   *result;
  230. {
  231.     int             ch;
  232.  
  233.     ch = buff_getc();
  234.     if ( ch == EOF ) {
  235.         return( TRUE );
  236.     }
  237.     *result = (dword)((uchar)ch);
  238.  
  239.     ch = buff_getc();
  240.     if ( ch == EOF ) {
  241.         return( TRUE );
  242.     }
  243.     *result += (dword)((uchar)ch) << 8;
  244.  
  245.     ch = buff_getc();
  246.     if ( ch == EOF ) {
  247.         return( TRUE );
  248.     }
  249.     *result += (dword)((uchar)ch) << 16;
  250.     ch = buff_getc();
  251.     if ( ch == EOF ) {
  252.         return( TRUE );
  253.     }
  254.     *result += (dword)((uchar)ch) << 24;
  255.  
  256.     return( FALSE );
  257. }
  258.  
  259. int check_getv( value, flag )
  260.     dword   *value;
  261.     int             flag;
  262. {
  263.     int             result;
  264.  
  265.     if ( flag ) {
  266.         result = check_getl( value );
  267.     } else {
  268.         result = check_getw( value );
  269.     }
  270.     return( result );
  271. }
  272.  
  273. int get_checkc( offset )
  274.     dword   *offset;
  275. {
  276.     int     dcheck;
  277.  
  278.     dcheck = data_check( 1 );
  279.  
  280.     if ( dcheck != NORMAL && dcheck != BAD ) {
  281.         return( TRUE );                 /* Must be no labels or fixups */
  282.     }
  283.     return( check_getc( offset ) );
  284. }
  285.  
  286. void instr_opcode( text )
  287.     char    *text;
  288. {
  289.     if ( pass == 3 ) {
  290.         out_opcode( text );
  291.     }
  292.     tab_offset = 0;
  293.     inst_init();            /* Reset for next instruction */
  294. }
  295.  
  296. void instr_operand( text )
  297.     char    *text;
  298. {
  299.     if ( pass == 3 ) {
  300.         out_operand( text );
  301.     }
  302. }
  303.  
  304. int stub( byte, text, class )
  305.     uchar   byte;
  306.     char            *text;
  307.     int             class;
  308. {
  309.     byte = byte;               /* Prevent unused variable warnings */
  310.     text = text;               /* Prevent unused variable warnings */
  311.     class = class;              /* Prevent unused variable warnings */
  312.     return( 0 );
  313.  
  314. }
  315.  
  316. int in_out( byte, text, class )
  317.     uchar   byte;
  318.     char            *text;
  319.     int             class;
  320. {
  321.     int             dir;
  322.     int             size;
  323.     char            temp[50];
  324.  
  325.     dir  = ( byte & 0x02 ) >> 1;
  326.     size = ( byte & 0x01 );
  327.  
  328.     if ( size == 1 && size_large ) {
  329.         size = 2;
  330.     }
  331.     instr_opcode(text);
  332.  
  333.     if ( dir == 0 ) {
  334.         sprintf( temp, "%s,dx", regs[size][0] );
  335.     } else {
  336.         sprintf( temp, "dx,%s", regs[size][0] );
  337.     }
  338.     instr_operand(temp);
  339.  
  340.     class = class;              /* Prevent unused variable warnings */
  341.  
  342.     return(1);
  343. }
  344.  
  345. int string_byte( byte, text, class )
  346.     uchar   byte;
  347.     char            *text;
  348.     int             class;
  349. {
  350.     char            opcode[10];
  351.     char            operand[50];
  352.     int             size;
  353.     int             mode;
  354.     char            *format;
  355.  
  356.     class = class;                  /* Prevent unused variable warnings */
  357.  
  358.     size = byte & 0x01;
  359.     if ( size == 1 && size_large ) {
  360.         size = 2;
  361.     }
  362.  
  363.     switch( byte ) {
  364.         case 0xA4:
  365.         case 0xA5:
  366.             format = "%ses:[di],%s%s[si]";
  367.             mode = 0;
  368.             break;
  369.         case 0xA6:
  370.         case 0xA7:
  371.             format = "%ses:[di],%s%s[si]";
  372.             mode = 0;
  373.             break;
  374.         case 0xAA:
  375.         case 0xAB:
  376.             mode = 2;
  377.             break;
  378.         case 0xAC:
  379.         case 0xAD:
  380.             format = "%s%s[si]";
  381.             mode = 1;
  382.             break;
  383.         case 0xAE:
  384.         case 0xAF:
  385.             mode = 2;
  386.             break;
  387.     }
  388.  
  389.     strcpy( opcode, text );
  390.  
  391.     if ( over_seg == -1 ) {
  392.         switch( size ) {
  393.             case 0:     strcat(opcode,"b");     break;
  394.             case 1:     strcat(opcode,"w");     break;
  395.             case 2:     strcat(opcode,"d");     break;
  396.         }
  397.         instr_opcode(opcode);
  398.         return(1);
  399.     } else {
  400.         switch( mode ) {
  401.             case 0:
  402.                 sprintf( operand, format, sz_text[size],
  403.                                             sz_text[size], sregsc[over_seg] );
  404.                 break;
  405.             case 1:
  406.                 sprintf( operand, format, sz_text[size], sregsc[over_seg] );
  407.                 break;
  408.             case 2:                 /* No segment overide on */
  409.                 return( 0 );        /* SCAS instructions     */
  410.         }
  411.         instr_opcode( opcode );
  412.         instr_operand( operand );
  413.         return(1);
  414.     }
  415.  
  416. }
  417.  
  418. int one_byte( byte, text, class )
  419.     uchar   byte;
  420.     char            *text;
  421.     int             class;
  422. {
  423.     char            line[50];
  424.  
  425.     if ( strlen(text) == 0 ) {
  426.         return(0);
  427.     }
  428.  
  429.     reg_format( class, line, text, "%s", "%s\t%s" );
  430.  
  431.     instr_opcode(line);
  432.     byte = byte;               /* Prevent unused variable warnings */
  433.  
  434.     return(1);
  435. }
  436.  
  437. int two_byte( byte, text, class )
  438.     uchar   byte;
  439.     char            *text;
  440.     int             class;
  441. {
  442.     dword   offset;
  443.     char            line[50];
  444.     char            temp[50];
  445.  
  446.     if ( get_checkc( &offset ) ) {
  447.         return( 0 );
  448.     }
  449.  
  450.     reg_format( class, line, text, "%s\t", "%s\t%s," );
  451.  
  452.     out_hexize( offset, temp, 1 );      /* Convert 1 byte into hex */
  453.     strcat( line, temp );
  454.  
  455.     instr_opcode( line );
  456.  
  457.     byte = byte;                   /* Prevent unused varaible warnings */
  458.  
  459.     return(2);
  460. }
  461.  
  462. int two_ubyte( byte, text, class )
  463.     uchar   byte;
  464.     char            *text;
  465.     int             class;
  466. {
  467.     dword   offset;
  468.     char            line[50];
  469.  
  470.     if ( get_checkc( &offset ) ) {
  471.         return( 0 );
  472.     }
  473.  
  474.     if ( offset <= 127L ) {
  475.         sprintf( line, "%s+0%02lXh", text, offset );
  476.     } else {
  477.         sprintf( line, "%s-0%02lXh", text, 0x0100L - offset );
  478.     }
  479.     instr_opcode( line );
  480.  
  481.     byte = byte;               /* Prevent unused variable warnings */
  482.     class = class;              /* Prevent unused variable warnings */
  483.  
  484.     return(2);
  485. }
  486.  
  487. int three_byte( byte, text, class )
  488.     uchar   byte;
  489.     char            *text;
  490.     int             class;
  491. {
  492.     dword   offset;
  493.     int             dummy;
  494.     int             data_size;
  495.     int             size_tmp;
  496.     char            line[50];
  497.     char            temp[50];
  498.  
  499.     if ( over_seg != -1 ) {         /* No segment overide allowed */
  500.         return( 0 );
  501.     }
  502.  
  503.     reg_format( class, line, text, "%s\t", "%s\t%s," );
  504.  
  505.     size_tmp = size_large;
  506.  
  507.     if ( byte == 0xC2 || byte == 0xCA ) {       /* <RET jjkk>/<RETF jjkk> */
  508.         size_tmp = FALSE;
  509.         size_bytes = 2;
  510.     }
  511.  
  512.     data_size = size_bytes;
  513.  
  514.     switch( data_check( 1 ) ) {
  515.         case BAD:       return( 0 );
  516.         case LABEL:     return( 0 );
  517.         case FIXUP:     if ( fix_rec->word_sized
  518.                                 && fix_rec->extended == size_tmp ) {
  519.                             get_fix( temp, 2, TRUE, size_bytes,
  520.                                                     NEAR, FALSE, &dummy, DS );
  521.                             strcat( line, temp );
  522.                             adjust_assumes();
  523.                             instr_opcode( line );
  524.                             return( data_size+1 );
  525.                         } else {
  526.                             return( 0 );
  527.                         }
  528.         case NORMAL:    if ( check_getv( &offset, size_tmp ) ) {
  529.                             return( 0 );
  530.                         }
  531.                         out_hexize( offset, temp, size_bytes );
  532.                         strcat( line, temp );
  533.                         instr_opcode(line);
  534.                         return( data_size+1 );
  535.     }
  536.     return(0);
  537. }
  538.  
  539. int five_byte( byte, text, class )
  540.     uchar   byte;
  541.     char            *text;
  542.     int             class;
  543. {
  544.     dword   offset;
  545.     dword   segment;
  546.     int             size_known;
  547.     char            line[50];
  548.     char            temp[50];
  549.     int             data_size;
  550.  
  551.     if ( over_seg != -1 ) {         /* No segment overide allowed */
  552.         return(0);
  553.     }
  554.  
  555.     data_size = size_bytes;
  556.  
  557.     switch( data_check( 1 ) ) {
  558.         case BAD:
  559.             return( 0 );
  560.         case LABEL:
  561.             return( 0 );
  562.         case FIXUP:
  563.             if ( fix_rec->form != POINTER || fix_rec->extended != size_large ) {
  564.                 return( 0 );
  565.             }
  566.             get_fix( temp, 1, FALSE, size_bytes, NEAR, TRUE, &size_known, CS );
  567.             sprintf( line, "far ptr %s", temp );
  568.             break;
  569.         case NORMAL:
  570.             if ( check_getv( &offset, size_large ) ) {
  571.                 return( 0 );
  572.             }
  573.             if ( data_check(3) != NORMAL ) {
  574.                 return( 0 );
  575.             }
  576.             if ( check_getw( &segment ) ) {
  577.                 return( 0 );
  578.             }
  579.             out_hexize( segment, temp, 2 );      /* Convert 2 byte into hex */
  580.             strcpy( line, temp );
  581.             strcat( line, ":" );
  582.             out_hexize( offset, temp, size_bytes ); /* Convert 2/4 bytes into hex */
  583.             strcat( line, temp );
  584.             break; 
  585.     }
  586.  
  587.     adjust_assumes();
  588.  
  589.     instr_opcode( text );
  590.     instr_operand( line );
  591.  
  592.     byte = byte;               /* Prevent unused variable warnings */
  593.     class = class;              /* Prevent unused variable warnings */
  594.  
  595.     return( 3 + data_size );
  596. }
  597.  
  598. int one_a( byte, text, class )
  599.     uchar   byte;
  600.     char            *text;
  601.     int             class;
  602. {
  603.     char            line[50];
  604.  
  605.     if ( size_large ) {
  606.         reg_format( class, line, text, "%s\teax", "%s\teax,%s" );
  607.     } else {
  608.         reg_format( class, line, text, "%s\tax", "%s\tax,%s" );
  609.     }
  610.  
  611.     instr_opcode(line);
  612.  
  613.     byte = byte;                   /* Prevent unused varaible warnings */
  614.  
  615.     return(1);
  616. }
  617.  
  618. int two_a( byte, text, class )
  619.     uchar   byte;
  620.     char            *text;
  621.     int             class;
  622. {
  623.     int             size;
  624.     dword   offset;
  625.     char            line[50];
  626.  
  627.     size = (byte & 0x01);
  628.  
  629.     if ( check_getc( &offset ) ) {
  630.         return( 0 );
  631.     }
  632.  
  633.     if ( size == 0 ) {
  634.         sprintf( line, "0%02lXh,al", offset );
  635.     } else {
  636.         sprintf( line, "0%02lXh,ax", offset );
  637.     }
  638.     instr_opcode( text );
  639.     instr_operand(line);
  640.  
  641.     byte = byte;               /* Prevent unused variable warnings */
  642.     class = class;              /* Prevent unused variable warnings */
  643.  
  644.     return(2);
  645. }
  646.  
  647. int three_a( byte, text, class )
  648.     uchar   byte;
  649.     char            *text;
  650.     int             class;
  651. {
  652.     int             dir;
  653.     int             reg_size;
  654.     int             data_size;
  655.     int             type;
  656.     int             size_known;
  657.     dword   offset;
  658.     char            line[50];
  659.     char            seg_text[10];
  660.     char            temp[50];
  661.     char            temp2[15];
  662.     int             ref_seg;
  663.  
  664.     data_size = addr_bytes;
  665.  
  666.     dir  = ( byte & 0x02 ) >> 1;
  667.     reg_size = ( byte & 0x01 );
  668.  
  669.     if ( reg_size == 1 && size_large ) {
  670.         reg_size = 2;
  671.     }
  672.     type = reg_size_to_type(reg_size);
  673.  
  674.     if ( over_seg != -1 ) {                 /* Any previous segment overide? */
  675.         ref_seg = 17+over_seg;
  676.         strcpy( seg_text, sregsc[over_seg] );
  677.     } else {
  678.         ref_seg = DS;
  679.         seg_text[0] = '\0';
  680.     }
  681.  
  682.     switch( data_check( 1 ) ) {
  683.         case BAD:
  684.             return( 0 );
  685.         case LABEL:     
  686.             return( 0 );
  687.         case FIXUP:
  688.             if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  689.                 get_fix( temp, 0, FALSE, size_bytes, type, TRUE,
  690.                                                         &size_known, ref_seg );
  691.             } else {
  692.                 return( 0 );
  693.             }
  694.             strcpy( line, "" );
  695.             if ( compatibility == 2 ) {
  696.                 strcat( line, seg_text );
  697.                 strcat( line, " " );
  698.                 if ( !size_known ) {
  699.                     strcat( line, type_to_text(type) );
  700.                 }
  701.             } else {
  702.                 if ( !size_known ) {
  703.                     strcat( line, type_to_text(type) );
  704.                 }
  705.                 strcat( line, seg_text );
  706.             }
  707.             strcat( line, temp );
  708.             break;
  709.         case NORMAL:
  710.             if ( check_getv( &offset, addr_large ) ) {
  711.                 return( 0 );
  712.             }
  713.             out_hexize( offset, temp2, addr_bytes );    /* Make hex digits */
  714.  
  715.             if ( compatibility == 2 ) {
  716.                 sprintf( line, "%s .%s", seg_text, temp2 );
  717.             } else {
  718.                 if ( over_seg == -1 ) {
  719.                     sprintf( line, "ds:[%s]", temp2 );
  720.                 } else {
  721.                     sprintf( line, "%s[%s]", seg_text, temp2 );
  722.                 }
  723.             }
  724.             break;
  725.     }
  726.  
  727.     if ( dir == 0 ) {
  728.         sprintf( temp, "%s,%s", regs[reg_size][0], line );
  729.     } else {
  730.         sprintf( temp, "%s,%s", line, regs[reg_size][0] );
  731.     }
  732.  
  733.     adjust_assumes();
  734.  
  735.     instr_opcode( text );
  736.     instr_operand( temp );
  737.  
  738.     class = class;              /* Prevent unused variable warnings */
  739.  
  740.     return( 1 + data_size );
  741. }
  742.  
  743. int enter( byte, text, class )
  744.     uchar   byte;
  745.     char            *text;
  746.     int             class;
  747. {
  748.     dword   num_bytes;
  749.     dword   nest_level;
  750.     char            line[50];
  751.  
  752.     switch( data_check(1) ) {
  753.         case BAD:
  754.         case LABEL:
  755.         case FIXUP:
  756.             return( 0 );
  757.         case NORMAL:
  758.             if ( check_getw(&num_bytes) ) {
  759.                 return( 0 );
  760.             }
  761.             if ( check_getc(&nest_level) ) {
  762.                 return( 0 );
  763.             }
  764.             sprintf( line, "0%04lXh,0%02lXh", num_bytes, nest_level );
  765.             break;
  766.     }
  767.     instr_opcode( text );
  768.     instr_operand( line );
  769.  
  770.     byte = byte;               /* Prevent unused variable warnings */
  771.     class = class;              /* Prevent unused variable warnings */
  772.  
  773.     return(4);
  774. }
  775.  
  776. int check_forward( inst_table, method )
  777.     INST_T          inst_table[];
  778.     int             method;
  779. {
  780.     dword   byte;
  781.     int             data;
  782.     int             valid;
  783.     extern char     *buff_cur;
  784.     char            *buff_save;
  785.  
  786.     buff_save = buff_cur;
  787.     /*
  788.     ** The next byte must be a valid instruction
  789.     */
  790.     if ( get_checkc( &byte ) ) {
  791.         return( 0 );
  792.     }
  793.     data = (uchar)byte;
  794.  
  795. #ifdef DEBUG
  796.     printf("Checking forward with byte [%02X]\n", data );
  797. #endif
  798.  
  799.     inst_offset += 1;
  800.  
  801.     if ( method == 0 && pass == 3 ) {
  802.         pass = 2;               /* Temporarily disable output */
  803.         valid = (*inst_table[data].rtn)
  804.                     ((uchar)data,
  805.                     inst_table[data].text,
  806.                     inst_table[data].special );
  807.         pass = 3;
  808.     } else {
  809.         valid = (*inst_table[data].rtn)
  810.                     ((uchar)data,
  811.                     inst_table[data].text,
  812.                     inst_table[data].special );
  813.     }
  814.  
  815.     inst_offset -= 1;
  816.  
  817.     if ( method == 0 || valid == 0 ) {
  818.         buff_cur = buff_save;
  819.     }
  820.  
  821.     return( valid );
  822. }
  823.  
  824. int seg_over( byte, text, class )
  825.     uchar   byte;
  826.     char            *text;
  827.     int             class;
  828. {
  829.     int             valid;
  830.     int             save_seg;
  831.  
  832.     text = text;               /* Prevent unused variable warnings */
  833.     class = class;              /* Prevent unused variable warnings */
  834.  
  835.     save_seg = over_seg;
  836.  
  837.     if ( byte >= 0x64 ) {
  838.         over_seg = 4 + byte - 0x64;
  839.     } else {
  840.         over_seg = (byte & 0x18) >> 3;
  841.     }
  842.  
  843.     valid = check_forward( instr, 1 );
  844.     if ( valid ) {
  845.         return( valid+1 );
  846.     } else {
  847.         over_seg = save_seg;
  848.         return( 0 );
  849.     }
  850. }
  851.  
  852. int opsize_over( byte, text, class )
  853.     uchar   byte;
  854.     char            *text;
  855.     int             class;
  856. {
  857.     int             valid;
  858.     int             save_large;
  859.     int             save_bytes;
  860.  
  861.     byte = byte;               /* Prevent unused variable warnings */
  862.     text = text;               /* Prevent unused variable warnings */
  863.     class = class;              /* Prevent unused variable warnings */
  864.  
  865.     save_large = size_large;
  866.     save_bytes = size_bytes;
  867.  
  868.     size_large = !size_large;       /* Toggle size */
  869.     if ( size_bytes == 2 ) {
  870.         size_bytes = 4;
  871.     } else {
  872.         size_bytes = 2;
  873.     }
  874.     over_opsize = TRUE;
  875.  
  876.     valid = check_forward( instr, 1 );
  877.     if ( valid ) {
  878.         return( valid+1 );
  879.     } else {
  880.         size_large = save_large;
  881.         size_bytes = save_bytes;
  882.         return( 0 );
  883.     }
  884. }
  885.  
  886. int adrsize_over( byte, text, class )
  887.     uchar   byte;
  888.     char            *text;
  889.     int             class;
  890. {
  891.     int             valid;
  892.     int             save_large;
  893.     int             save_bytes;
  894.  
  895.     byte = byte;               /* Prevent unused variable warnings */
  896.     text = text;               /* Prevent unused variable warnings */
  897.     class = class;              /* Prevent unused variable warnings */
  898.  
  899.     save_large = addr_large;
  900.     save_bytes = addr_bytes;
  901.  
  902.     addr_large = !addr_large;           /* Toggle address */
  903.     if ( addr_bytes == 2 ) {
  904.         addr_bytes = 4;
  905.     } else {
  906.         addr_bytes = 2;
  907.     }
  908.     over_adrsize = TRUE;
  909.  
  910.     valid = check_forward( instr, 1 );
  911.     if ( valid ) {
  912.         return( valid+1 );
  913.     } else {
  914.         addr_large = save_large;
  915.         addr_bytes = save_bytes;
  916.         return( 0 );
  917.     }
  918. }
  919.  
  920. int wait( byte, text, class )
  921.     uchar   byte;
  922.     char            *text;
  923.     int             class;
  924. {
  925.     int             valid;
  926.  
  927.     byte = byte;               /* Prevent unused variable warnings */
  928.     class = class;              /* Prevent unused variable warnings */
  929.  
  930.     fp_opcode[0] = '\0';
  931.  
  932.     valid = check_forward( instr, 0 );
  933.     if ( !valid ) {
  934.         instr_opcode(text);
  935.         return(1);
  936.     } else {
  937.         if ( strlen(fp_opcode) == 0 ) {
  938.             instr_opcode( text );
  939.             return( 1 );
  940.         } else {
  941.             fp_wait = TRUE;         /* Will be reset by "esc" routine */
  942.             hex_finish = FALSE;
  943.             return( 1 );
  944.         }
  945.     }
  946. }
  947.  
  948. int prefix( byte, text, class )
  949.     uchar   byte;
  950.     char            *text;
  951.     int             class;
  952. {
  953.     int             valid;
  954.  
  955.     valid = check_forward( instr, 0 );
  956.  
  957.     byte = byte;               /* Prevent unused variable warnings */
  958.     class = class;              /* Prevent unused variable warnings */
  959.  
  960.     if ( valid ) {
  961.         instr_opcode( text );
  962.         tab_offset = 1;
  963.         hex_finish = FALSE;
  964.         return( 1 );
  965.     } else {
  966.         return( 0 );
  967.     }
  968. }
  969.  
  970. int extra( byte, text, class )
  971.     uchar   byte;
  972.     char            *text;
  973.     int             class;
  974. {
  975.     int             result;
  976.  
  977.     result = check_forward( ex_instr, 1 );
  978.  
  979.     byte = byte;               /* Prevent unused variable warnings */
  980.     text = text;
  981.     class = class;
  982.  
  983.     if ( result == 0 ) {
  984.         return( 0 );
  985.     } else {
  986.         return( result+1 );
  987.     }
  988. }
  989.  
  990. int disp8( byte, text, class )
  991.     uchar   byte;
  992.     char            *text;
  993.     int             class;
  994. {
  995.     int             dcheck;
  996.     char            line[60];
  997.     char            *short_text;
  998.     dword   offset;
  999.     dword   dest;
  1000.     PUB_T           *pub_rec;
  1001.  
  1002.     if ( over_seg != -1 ) {             /* No segment overide allowed */
  1003.         return( 0 );
  1004.     }
  1005.  
  1006.     dcheck = data_check(1);
  1007.  
  1008.     if ( dcheck != NORMAL && dcheck != BAD ) {
  1009.         return( 0 );
  1010.     }
  1011.  
  1012.     if ( check_getc( &offset ) ) {
  1013.         return( 0 );
  1014.     }
  1015.  
  1016.     if ( offset == 0xFFFFFFFFL ) {      /* This would generate a label in  */
  1017.         return( 0 );                    /* the middle of the jmp statement */
  1018.     }                                   /* thereby preventing it anyway    */
  1019.  
  1020.     /*
  1021.     ** Special 'SHORT' for small jumps 
  1022.     */
  1023.     short_text = "";
  1024.     if ( compatibility != 2 ) {
  1025.         if ( byte == 0xEB || segment_mode == 386 ) {
  1026.             short_text = "short ";
  1027.         }
  1028.     }
  1029.  
  1030.     dest = inst_offset + (signed char)offset + 2;
  1031.  
  1032.     pub_rec = check_public( 1, segment, dest, 'L' );
  1033.  
  1034.     if ( pub_rec ) {
  1035.         pub_rec->type = NEAR;
  1036.         offset = dest - pub_rec->offset;
  1037.         if ( offset > 0 ) {
  1038.             sprintf( line, "%s%s + 0%04lXh", 
  1039.                                 short_text, pub_rec->name, offset );
  1040.         } else {
  1041.             sprintf( line, "%s%s", short_text, pub_rec->name );
  1042.         }
  1043.     } else {
  1044.         if ( compatibility == 2 ) {
  1045.             sprintf( text, " %s.0%04lXh", short_text, offset );
  1046.         } else {
  1047.             sprintf( text, "%s[%s:0%04lXh]", short_text, cseg_name, offset );
  1048.         }
  1049.     }
  1050.  
  1051.     instr_opcode( text );
  1052.     instr_operand( line );
  1053.  
  1054.     byte = byte;               /* Prevent unused variable warnings */
  1055.     class = class;
  1056.     return( 2 );
  1057. }
  1058.  
  1059. int disp16( byte, text, class )
  1060.     uchar   byte;
  1061.     char            *text;
  1062.     int             class;
  1063. {
  1064.     dword   offset;
  1065.     dword   dest;
  1066.     int             dummy;
  1067. #if 0
  1068.     int             bad_size;
  1069. #endif
  1070.     char            line[60];
  1071.     char            *short_text;
  1072.     PUB_T           *pub_rec;
  1073.     int             data_size;
  1074.  
  1075.     byte = byte;               /* Prevent unused variable warnings */
  1076.     class=class;              /* Prevent unused variable warnings */
  1077.  
  1078.     data_size = addr_bytes;
  1079.  
  1080.     if ( over_seg != -1 )               /* No segment overide allowed */
  1081.         return( 0 );
  1082.  
  1083.     switch( data_check( 1 ) ) {
  1084.     case BAD:
  1085.          return( 0 );
  1086.     case LABEL:
  1087.          return( 0 );
  1088.     case FIXUP:
  1089.          if ( fix_rec->word_sized && fix_rec->extended == addr_large
  1090.                                   && fix_rec->relate == 0 ) {
  1091.              get_fix( line, 1, FALSE, size_bytes, NEAR, TRUE, &dummy, CS );
  1092.              adjust_assumes();
  1093.              instr_opcode( text );
  1094.              instr_operand( line );
  1095.              return( 1 + data_size );
  1096.          } else {
  1097.              return( 0 );
  1098.          }
  1099.     case NORMAL:
  1100.          if ( check_getv( &offset, addr_large ) ) {
  1101.              return( 0 );
  1102.          }
  1103.          /* note: the next if actually checks for 1 byte too far in
  1104.          ** the negative direction. but this is ok, because it would be
  1105.          ** replaced by a short jmp
  1106.          */
  1107.          if ( offset < 0x80 || offset >= 0xFFFFFF7FL ) {
  1108. #if 0
  1109.              bad_size = TRUE;
  1110. #endif
  1111.              short_text = "near ptr ";
  1112.          } else {
  1113.              short_text = "";
  1114. #if 0
  1115.              bad_size = FALSE;
  1116. #endif
  1117.          }
  1118.  
  1119.          dest = inst_offset + offset + addr_bytes + 1;
  1120.          pub_rec = check_public( 1, segment, dest, 'L' );
  1121.  
  1122.          if ( pub_rec ) {
  1123.              offset = dest - pub_rec->offset;
  1124.              if ( offset > 0L ) {
  1125.                  if ( addr_large ) {
  1126.                      sprintf( line, "%s%s + 0%08lXh", short_text,
  1127.                               pub_rec->name, offset );
  1128.                  } else {
  1129.                      sprintf( line, "%s%s + 0%04lXh", short_text,
  1130.                               pub_rec->name, offset );
  1131.                  }
  1132.              } else {
  1133.                  sprintf( line, "%s%s", short_text, pub_rec->name );
  1134.              }
  1135.          } else {
  1136.              if ( compatibility == 2 ) {
  1137.                  if ( addr_large ) {
  1138.                      sprintf( line, "%s .0%08lXh", short_text, offset );
  1139.                  } else {
  1140.                      sprintf( line, "%s .0%04lXh", short_text, offset );
  1141.                  }
  1142.              } else {
  1143.                  if ( addr_large ) {
  1144.                      sprintf( line, "%s[%s:0%08lXh]", short_text,
  1145.                               cseg_name, offset );
  1146.                  } else {
  1147.                      sprintf( line, "%s[%s:0%04lXh]", short_text,
  1148.                               cseg_name, offset );
  1149.                  }
  1150.              }
  1151.          }
  1152.  
  1153.          instr_opcode( text );
  1154.          instr_operand( line );
  1155. #if 0
  1156.          if ( bad_size ) {
  1157.              if ( pass == 3 ) {
  1158.                  out_comment( "Large jump translated into short" );
  1159.              }
  1160.              instr_opcode( "nop" );
  1161.              if ( pass == 3 ) {
  1162.                  out_comment( "Nop inserted to retain proper length" );
  1163.              }
  1164.          }
  1165. #endif
  1166.          return( 1 + data_size );
  1167.     }
  1168.     return(0);
  1169. }
  1170.  
  1171. int two_bcd( byte, text, class )
  1172.     uchar   byte;
  1173.     char            *text;
  1174.     int             class;
  1175. {
  1176.     dword   offset;
  1177.  
  1178.     byte = byte;               /* Prevent unused variable warnings */
  1179.     class = class;              /* Prevent unused variable warnings */
  1180.  
  1181.     if ( check_getc( &offset ) ) {
  1182.         return( 0 );
  1183.     }
  1184.  
  1185.     if ( offset == 0x0AL ) {
  1186.         instr_opcode( text );
  1187.         return(2);
  1188.     } else {
  1189.         return( 0 );
  1190.     }
  1191. }
  1192.  
  1193. int mod0( ref_mode, sib_offset,sib_text, text, r_m, type, size_known )
  1194.     int             ref_mode;
  1195.     int             sib_offset;
  1196.     char            *sib_text;
  1197.     char            *text;
  1198.     uchar   r_m;
  1199.     int             type;
  1200.     int             *size_known;
  1201. {
  1202.     dword   offset;
  1203.     int             result;
  1204.     PUB_T           *pub_rec;
  1205.     STRUC_T         *pub_struct;
  1206.     int             ref_seg;
  1207.     char            this_member[NAMESIZE+1+1];  /* 1 for ., 1 for \0 */
  1208.     char            temp[16];
  1209.  
  1210.     this_member[0] = '\0';
  1211.  
  1212.     if ( (r_m == 6 && !addr_large) || (r_m == 5 && addr_large) ) {
  1213.         if ( over_seg != -1 ) {
  1214.             ref_seg = 17+over_seg;
  1215.         } else {
  1216.             ref_seg = DS;
  1217.         }
  1218.         switch( data_check( 2+sib_offset ) ) {
  1219.             case BAD:
  1220.                 result = -1;
  1221.                 return( result );
  1222.             case LABEL:
  1223.                 result = -1;
  1224.                 return( result );
  1225.             case FIXUP:
  1226.                 if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  1227.                     get_fix( text, 0, FALSE, size_bytes, 
  1228.                                             type, TRUE, size_known, ref_seg );
  1229.                     if ( strlen(sib_text) ) {
  1230.                         strcat( text, "[" );
  1231.                         strcat( text, sib_text );
  1232.                         strcat( text, "]" );
  1233.                     }
  1234.                     result = addr_bytes+sib_offset;
  1235.                 } else {
  1236.                     result = -1;
  1237.                 }
  1238.                 return( result );
  1239.             case NORMAL:
  1240.                 if ( check_getv( &offset, size_large ) ) {
  1241.                     result = -1;
  1242.                     return( result );
  1243.                 }
  1244.                 if ( add_labels ) {
  1245.                     pub_rec = check_public( 0, 0, offset, 'S' );
  1246.                 } else {
  1247.                     pub_rec = NULL;
  1248.                 }
  1249.                 if ( pub_rec ) {
  1250.                     offset -= pub_rec->offset;
  1251.                     pub_struct = pub_rec->structure;
  1252.                     if ( pub_struct ) {
  1253.                         find_member( this_member, pub_struct, &offset );
  1254.                     }
  1255.                     if ( offset != 0 ) {
  1256.                         out_hexize( offset, temp, size_bytes );
  1257.                         sprintf( text, "%s%s + %s",
  1258.                                  pub_rec->name, this_member, temp );
  1259.                     } else {
  1260.                         sprintf( text, "%s%s", pub_rec->name, this_member );
  1261.                     }
  1262.                 } else {
  1263.                     out_hexize( offset, temp, size_bytes );
  1264.                     if ( compatibility == 2 ) {
  1265.                         sprintf( text, " .%s", temp );
  1266.                     } else {
  1267.                         if ( over_seg == -1 ) {
  1268.                             sprintf( text, "ds:[%s", temp );
  1269.                         } else {
  1270.                             sprintf( text, "[%s", temp );
  1271.                         }
  1272.                         if ( strlen( sib_text ) ) {
  1273.                             strcat( text, "+" );
  1274.                             strcat( text, sib_text );
  1275.                         }
  1276.                         strcat( text, "]" );
  1277.                     }
  1278.                 }
  1279.                 result = addr_bytes+sib_offset;
  1280.                 *size_known = FALSE;
  1281.                 return( result );
  1282.         }
  1283.     }
  1284.     if ( addr_large ) {
  1285.         strcpy( text, addr_386m[r_m] );
  1286.     } else {
  1287.         strcpy( text, addr_mode[r_m] );
  1288.     }
  1289.     if ( strlen( sib_text ) ) {
  1290.         strcat( text, "+" );
  1291.         strcat( text, sib_text );
  1292.     }
  1293.     strcat( text, "]" );
  1294.     result = sib_offset;
  1295.     *size_known = TRUE;
  1296.     return( result );
  1297. }
  1298.  
  1299. int mod1( ref_mode, sib_offset, sib_text, text, r_m )
  1300.     int             ref_mode;
  1301.     int             sib_offset;
  1302.     char            *sib_text;
  1303.     char            *text;
  1304.     uchar   r_m;
  1305. {
  1306.     char            temp[50];
  1307.     dword   offset;
  1308.     int             result;
  1309.     uchar   zero_rm;
  1310.  
  1311.     if ( check_getc( &offset ) ) {
  1312.         result = -1;
  1313.     } else {
  1314.         if ( addr_large ) {
  1315.             /*
  1316.             ** Assembler should have optimized
  1317.             */
  1318.             zero_rm = 5;
  1319.             strcpy( text, addr_386m[r_m] );
  1320.         } else {
  1321.             /*
  1322.             ** Assembler should have optimized
  1323.             */
  1324.             zero_rm = 6;
  1325.             strcpy( text, addr_mode[r_m] );
  1326.         }
  1327.         if ( strlen(sib_text) ) {
  1328.             strcat( text, "+" );
  1329.             strcat( text, sib_text );
  1330.         }
  1331.         if ( offset >= 0x80 ) {
  1332.             sprintf( temp, "-0%02lXh", 0x0100L-offset );
  1333.         } else {
  1334.             if ( offset == 0L ) {
  1335.                 if ( r_m == zero_rm ) {
  1336.                     temp[0] = '\0';
  1337.                 } else {
  1338.                     return( -1 );
  1339.                 }
  1340.             } else {
  1341.                 sprintf( temp, "+0%02lXh", offset );
  1342.             }
  1343.         }
  1344.         if ( compatibility == 2 ) {
  1345.             strcat( text, "]" );
  1346.             strcat( text, temp );
  1347.         } else {
  1348.             strcat( text, temp );
  1349.             strcat( text, "]" );
  1350.         }
  1351.         result = 1 + sib_offset;
  1352.     }
  1353.     return( result );
  1354. }
  1355.  
  1356. int mod2( ref_mode, sib_offset, sib_text, text, r_m, type, size_known )
  1357.     int             ref_mode;
  1358.     int             sib_offset;
  1359.     char            *sib_text;
  1360.     char            *text;
  1361.     uchar   r_m;
  1362.     int             type;
  1363.     int             *size_known;
  1364. {
  1365.     dword   offset;
  1366.     int             result;
  1367.     char            temp[50];
  1368.     char            *sign;
  1369.     int             ref_seg;
  1370.  
  1371.     if ( r_m == 2 || r_m == 3 ) {
  1372.         ref_seg = SS;               /* SS relative addressing modes */
  1373.     } else {
  1374.         ref_seg = DS;
  1375.     }
  1376.     if ( over_seg != -1 ) {
  1377.         ref_seg = 17+over_seg;
  1378.     }
  1379.  
  1380.     switch( data_check(2+sib_offset) ) {
  1381.         case BAD:
  1382.             result = -1;
  1383.             break;
  1384.         case LABEL:
  1385.             result = -1;
  1386.             break;
  1387.         case FIXUP:
  1388.             if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  1389.                 get_fix( temp, 0, FALSE, addr_bytes,
  1390.                                             type, TRUE, size_known, ref_seg );
  1391.                 if ( compatibility == 2 ) {
  1392.                     strcpy( text, temp );
  1393.                     strcat( text, addr_mode[r_m] );
  1394.                 } else {
  1395.                     if ( addr_large ) {
  1396.                         strcpy( text, addr_386m[r_m] );
  1397.                     } else {
  1398.                         strcpy( text, addr_mode[r_m] );
  1399.                     }
  1400.                     if ( strlen(sib_text) ) {
  1401.                         strcat( text, "+" );
  1402.                         strcat( text, sib_text );
  1403.                     }
  1404.                     strcat( text, "+" );
  1405.                     strcat( text, temp );
  1406.                 }
  1407.                 strcat( text, "]" );
  1408.                 result = addr_bytes+sib_offset;
  1409.             } else {
  1410.                 result = -1;
  1411.             }
  1412.             break;
  1413.         case NORMAL:
  1414.             if ( check_getv( &offset, addr_large ) ) {
  1415.                 result = -1;
  1416.             } else {
  1417.                 if ( offset == 0x00000000L ) { 
  1418.                     return( -1 );       /* Assembler should have optimized */
  1419.                 }
  1420.                 if ( addr_large ) {
  1421.                     strcpy( text, addr_386m[r_m] );
  1422.                 } else {
  1423.                     strcpy( text, addr_mode[r_m] );
  1424.                 }
  1425.                 if ( strlen(sib_text) ) {
  1426.                     strcat( text, "+" );
  1427.                     strcat( text, sib_text );
  1428.                 }
  1429.                 if ( offset > 0x80000000L ) {
  1430.                     offset = -offset;
  1431.                     sign = "-";
  1432.                 } else {
  1433.                     sign = "+";
  1434.                 }
  1435.                 out_hexize( offset, temp, addr_bytes );
  1436.                 if ( compatibility == 2 ) {
  1437.                     strcat( text, "]" );
  1438.                     strcat( text, sign );
  1439.                     strcat( text, temp );
  1440.                 } else {
  1441.                     strcat( text, sign );
  1442.                     strcat( text, temp );
  1443.                     strcat( text, "]" );
  1444.                 }
  1445.                 result = addr_bytes+sib_offset;
  1446.                 *size_known = TRUE;
  1447.             }
  1448.             break;
  1449.     }
  1450.     return( result );
  1451. }
  1452.  
  1453. int mod3( ref_mode, text, r_m, type, type_known )
  1454.     int             ref_mode;
  1455.     char            *text;
  1456.     uchar   r_m;
  1457.     int             type;
  1458.     int             *type_known;
  1459. {
  1460.     switch( type ) {
  1461.         case BYTE_PTR:  strcpy( text, regs[0][r_m] );   break;
  1462.         case WORD_PTR:  strcpy( text, regs[1][r_m] );   break;
  1463.         case DWORD_PTR: strcpy( text, regs[2][r_m] );   break;
  1464.         default:        strcpy( text, regs[3][r_m] );   break;
  1465.     }
  1466.     *type_known = TRUE;
  1467.     return( 0 );
  1468. }
  1469.  
  1470. int do_sib( text, base )
  1471.     char            *text;
  1472.     uchar   *base;
  1473. {
  1474.     dword   sib_byte;
  1475.     int             ss;
  1476.     int             idx;
  1477.  
  1478.     switch( data_check(2) ) {
  1479.         case LABEL:
  1480.             return( -1 );
  1481.         case FIXUP:
  1482.             return( -1 );
  1483.         case BAD:
  1484.         case NORMAL:
  1485.             if ( check_getc( &sib_byte ) ) {
  1486.                 return( -1 );
  1487.             }
  1488.             ss    = (int)(sib_byte & 0xC0L) >> 6;
  1489.             idx   = (int)(sib_byte & 0x38L) >> 3;
  1490.             *base = (uchar)(sib_byte & 0x07L);
  1491.             if ( idx == 0x04 ) {            /* For special [ESP] */
  1492.                 if ( ss != 0 ) {
  1493.                     return( -1 );
  1494.                 } else {
  1495.                     strcpy( text, "" );
  1496.                 }
  1497.             } else {
  1498.                 strcat( text, regs[2][idx] );
  1499.                 strcat( text, sib_scale[ss] );
  1500.             }
  1501.             return( 1 );
  1502.     }
  1503. }
  1504.  
  1505. int do_mod_rm( line, mod, r_m, type, size_needed, ref_mode )
  1506.     char            *line;
  1507.     uchar   mod;
  1508.     uchar   r_m;
  1509.     int             type;
  1510.     int             size_needed;
  1511.     int             ref_mode;
  1512. {
  1513.     int             size_known;
  1514.     int             sib_offset;
  1515.     char            sib_text[50];
  1516.     char            temp2[50];
  1517.     int             result;
  1518.     
  1519.     size_known = FALSE;
  1520.  
  1521.     strcpy( sib_text, "" );
  1522.     sib_offset = 0;
  1523.  
  1524.     if ( addr_large ) {
  1525.         if ( r_m == 4 && mod != 3 ) {
  1526.             /* Get result and new r_m */
  1527.             sib_offset = do_sib( sib_text, &r_m );
  1528.             if ( sib_offset == -1 ) {
  1529.                 return( -1 );
  1530.             }
  1531.         }
  1532.     }
  1533.     switch( mod ) {
  1534.         case 0: result = mod0( ref_mode, sib_offset, sib_text, temp2,
  1535.                                             r_m, type, &size_known );
  1536.                 break;
  1537.         case 1: result = mod1( ref_mode, sib_offset, sib_text, temp2, r_m );
  1538.                 size_known = TRUE;
  1539.                 break;
  1540.         case 2: result = mod2( ref_mode, sib_offset, sib_text, temp2,
  1541.                                             r_m, type, &size_known );
  1542.                 break;
  1543.         case 3: result = mod3( ref_mode, temp2, r_m, type, &size_known );
  1544.                 size_needed = FALSE;
  1545.                 break;
  1546.     }
  1547.  
  1548.     if ( result != -1 ) {
  1549.         if ( compatibility == 2 ) {
  1550.             if ( over_seg != -1 ) {         /* Any previous segment overide? */
  1551.                 strcat( line, sregsc[over_seg] );
  1552.                 strcat( line, " " );
  1553.             }
  1554.             if ( !size_known || size_needed ) {
  1555.                 strcat( line, type_to_text(type) );
  1556.             }
  1557.         } else {
  1558.             /*
  1559.             ** If the size is already known, then we don't need 'xxxx' ptr text
  1560.             */
  1561.             if ( !size_known || size_needed ) {
  1562.                 strcat( line, type_to_text(type) );
  1563.             }
  1564.             if ( over_seg != -1 ) {         /* Any previous segment overide? */
  1565.                 strcat( line, sregsc[over_seg] );
  1566.             }
  1567.         }
  1568.         strcat( line, temp2 );
  1569.     }
  1570.     return( result );
  1571. }
  1572.  
  1573. int byte_immed( text, additional, sign )
  1574.     char            *text;
  1575.     int             additional;
  1576.     int             sign;
  1577. {
  1578.     int             dcheck;
  1579.     dword   offset;
  1580.  
  1581.     dcheck = data_check( additional+2 );
  1582.  
  1583.     switch( dcheck ) {
  1584.         case LABEL:     return( 1 );
  1585.         case FIXUP:     return( 1 );
  1586.         case BAD:
  1587.         case NORMAL:
  1588.             if ( check_getc( &offset ) ) {
  1589.                 return( 1 );
  1590.             }
  1591.             if ( sign ) {
  1592.                 if ( offset <= 0x7F ) {
  1593.                     sprintf( text, "+0%02lXh", offset );
  1594.                 } else {
  1595.                     sprintf( text, "-0%02lXh", 0x0100L-offset );
  1596.                 }
  1597.             } else {
  1598.                 out_hexize( offset, text, 1 );
  1599.             }
  1600.             break;
  1601.     }
  1602.     return( 0 );
  1603. }
  1604.  
  1605. int word_immed( text, additional )
  1606.     char            *text;
  1607.     int             additional;
  1608. {
  1609.     int             dcheck;
  1610.     int             dummy;
  1611.     dword   offset;
  1612.  
  1613.     dcheck = data_check( additional+2 );
  1614.  
  1615.     switch( dcheck ) {
  1616.         case LABEL:
  1617.             return( 1 );
  1618.         case FIXUP:
  1619.             if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  1620.                 get_fix( text, 2, TRUE, size_bytes, NEAR, FALSE, &dummy, DS );
  1621.             } else {
  1622.                 return( 1 );
  1623.             }
  1624.             break;
  1625.         case BAD:
  1626.             return( 1 );
  1627.         case NORMAL:
  1628.             if ( check_getv( &offset, size_large ) ) {
  1629.                 return( 1 );
  1630.             }
  1631.             if ( size_large ) {
  1632.                 out_hexize( offset, text, 4 );
  1633.             } else {
  1634.                 out_hexize( offset, text, 2 );
  1635.             }
  1636.             break;
  1637.     }
  1638.     return( 0 );
  1639. }
  1640.  
  1641.  
  1642. int mod_reg( byte, text, class )
  1643.     uchar   byte;
  1644.     char            *text;
  1645.     int             class;
  1646. {
  1647.     char            *opcode;
  1648.     int             dir;
  1649.     int             size;
  1650.     int             reg_size;
  1651.     int             size_needed;
  1652.     int             type;
  1653.     int             method;
  1654.     int             group;
  1655.     dword   mod_reg;
  1656.     uchar   mod;
  1657.     uchar   r_m;
  1658.     uchar   reg;
  1659.     int             additional;
  1660.     char            mem_text[50];
  1661.     char            reg_text[50];
  1662.     char            third_text[50];
  1663.     char            operands[80];
  1664.     int             ref_mode;
  1665.  
  1666.     if ( get_checkc( &mod_reg ) ) {
  1667.         return( 0 );
  1668.     }
  1669.  
  1670.     mod = (uchar)(((int)mod_reg & 0xC0) >> 6);
  1671.     reg = (uchar)(((int)mod_reg & 0x38) >> 3);
  1672.     r_m = (uchar)(((int)mod_reg & 0x07) >> 0);
  1673.  
  1674.     dir         = modrm_class[class].dir;
  1675.     size        = modrm_class[class].size;
  1676.     method      = modrm_class[class].method;
  1677.     group       = modrm_class[class].group;
  1678.     size_needed = modrm_class[class].size_needed;
  1679.     type        = modrm_class[class].type;
  1680.  
  1681.     ref_mode = 0;
  1682.  
  1683.     if ( group == 6 ) {
  1684.         if ( mod == 3 ) {
  1685.             if ( reg == 0 || reg == 1 || reg == 2 || reg == 3 ) {
  1686.                 addr_large = FALSE;         /* 286 only instructions */
  1687.                 size_large = FALSE;
  1688.             }
  1689.         }
  1690.         type = WORD_PTR;
  1691.         size_needed = TRUE;
  1692.     }
  1693.  
  1694.     reg_size = size;                /* 386 Segments effect register names */
  1695.     if ( reg_size == 1 && size_large ) {
  1696.         reg_size = 2;
  1697.     }
  1698.     if ( type == UNKNOWN ) {
  1699.         type = reg_size_to_type( reg_size );
  1700.     }
  1701.  
  1702.     if ( group == 0 ) {
  1703.         opcode = text;
  1704.     } else {
  1705.         opcode = op_grp[group-1][reg];
  1706.     }
  1707.     if ( strlen(opcode) == 0 ) {
  1708.         return( 0 );
  1709.     }
  1710.  
  1711.     if ( class == 26 ) {
  1712.         reg_size = 1;
  1713.     }
  1714.  
  1715.     if ( byte == 0x62 || byte == 0x63 ) {
  1716.         if ( byte == 0x63 ) {
  1717.             type = WORD_PTR;
  1718.         }
  1719.         size_needed = TRUE;     /* LAR, LSL, BOUND, ARPL need size */
  1720.     }
  1721.     if ( byte == 0xC4 || byte == 0xC5
  1722.            || byte == 0xB2 || byte == 0xB4 || byte == 0xB5 ) {
  1723.         size_needed = TRUE;
  1724.     }
  1725.  
  1726.     if ( group == 3 ) {         /* Group 3 has a test instruction which    */
  1727.         if ( reg == 0 ) {       /* needs an immediate value (byte or word) */
  1728.             method = 5 + size;  /* the rest of group 3 needs nothing       */
  1729.             dir = 0;
  1730.             size_needed = TRUE;
  1731.         } else {
  1732.             method = 0;
  1733.             if ( reg == 2 || reg == 3 ) {
  1734.                 size_needed = FALSE;
  1735.             } else {
  1736.                 size_needed = TRUE;
  1737.             }
  1738.         }
  1739.     }
  1740.  
  1741.     if ( group == 5 ) {                 /* Group 5 has call far and jump far */
  1742.         if ( reg == 3 || reg == 5 ) {   /* instructions which are dwords     */
  1743.                                         /* the rest of group 5 is words      */
  1744.             if ( size_large ) {
  1745.                 type = FWORD_PTR;
  1746.             } else {
  1747.                 type = DWORD_PTR;
  1748.             }
  1749.             size_needed = TRUE;
  1750.         } else {
  1751.             if ( reg == 0 || reg == 1 ) {
  1752.                 size_needed = TRUE;
  1753.             }
  1754.         }
  1755.     }
  1756.  
  1757.     if ( group == 7 ) {                 /* Group 7 has mostly FWORD sized    */
  1758.         if ( reg == 4 || reg == 6 ) {   /* EAs, but these two are WORD sized */
  1759.             type = WORD_PTR;
  1760.         }
  1761.     }
  1762.  
  1763.     if ( dir == 0 && mod == 3 && (class == 0 || class == 1) ) {
  1764.         /*
  1765.         ** Ambiguous!   eg. OBJ 20F8 = and al,bh => MASM 22C7
  1766.         ** This is because MASM prefers the first operand to be
  1767.         ** a register and the other operand to be a mem/reg.
  1768.         */
  1769.         return(0);
  1770.     }
  1771.  
  1772.     mem_text[0] = '\0';
  1773.     additional = do_mod_rm( mem_text, mod, r_m, type, size_needed, ref_mode );
  1774.     if ( additional == -1 ) {
  1775.         return( 0 );
  1776.     }
  1777.  
  1778.     switch( method ) {
  1779.         case 0:         /* No additional information (one operand only) */
  1780.             break;
  1781.         case 1:         /* Other operand is a register */
  1782.                         /* LES,LDS,BOUND,LSS,LFS,LGS, ARPL instructions */
  1783.                         /* revert to Word */
  1784.             if ( byte == 0xC4 || byte == 0xC5 || byte == 0x62 || byte == 0x63
  1785.                    || byte == 0xB2 || byte == 0xB4 || byte == 0xB5 ) {
  1786.                 reg_size = 1;
  1787.             }
  1788.  
  1789.             strcpy( reg_text, regs[reg_size][reg] );
  1790.             break;
  1791.         case 2:         /* Other operand is a segment register */
  1792.             if ( reg > 5 ) {    /* 0=ES,1=CS,2=SS,3=DS,4=FS,5=GS */
  1793.                 return( 0 );
  1794.             }
  1795.             strcpy( reg_text, sregs[reg] );
  1796.             break;
  1797.         case 3:         /* Other operand is 1 */
  1798.             strcpy( reg_text, "1" );
  1799.             break;
  1800.         case 4:         /* Other operand is register CL */
  1801.             strcpy( reg_text, "cl" );
  1802.             break;
  1803.         case 5:         /* Immediate byte value */
  1804.             if ( byte_immed(reg_text, additional,FALSE) ) {
  1805.                 return( 0 );
  1806.             }
  1807.             additional++;
  1808.             break;
  1809.         case 6:         /* Immediate word value (could be fixupp) */
  1810.             if ( word_immed(reg_text, additional) ) {
  1811.                 return( 0 );
  1812.             }
  1813.             if ( size_large ) {
  1814.                 additional += 4;
  1815.             } else {
  1816.                 additional += 2;
  1817.             }
  1818.             break;
  1819.         case 7:         /* Immediate signed byte value */
  1820.             if ( byte_immed(reg_text,additional,TRUE) ) {
  1821.                 return( 0 );
  1822.             }
  1823.             additional++;
  1824.             break;
  1825.         case 8:         /* IMUL (3 operands [reg,mem,immed word]) */
  1826.             strcpy( reg_text, regs[reg_size][reg] );
  1827.             if ( word_immed(third_text, additional) ) {
  1828.                 return(0);
  1829.             }
  1830.             additional += 2;
  1831.             break;
  1832.         case 9:         /* IMUL (3 operands [reg,mem,immed signed byte]) */
  1833.             strcpy( reg_text, regs[reg_size][reg] );
  1834.             if ( byte_immed(third_text, additional,TRUE) ) {
  1835.                 return(0);
  1836.             }
  1837.             additional += 1;
  1838.             break;
  1839.         case 10:        /* Control Register (CR0...) */
  1840.             strcpy( reg_text, cr_regs[reg] );
  1841.             break;
  1842.         case 11:        /* Debug Register (DR0...) */
  1843.             strcpy( reg_text, dr_regs[reg] );
  1844.             break;
  1845.         case 12:
  1846.             strcpy( reg_text, tr_regs[reg] );
  1847.             break;
  1848.         case 13:
  1849.             strcpy( reg_text, regs[reg_size][reg] );
  1850.             strcpy( third_text, "cl" );
  1851.             break;
  1852.     }
  1853.  
  1854.     if ( dir & 0x01 ) {
  1855.         sprintf( operands, dir_fmt[dir], reg_text, mem_text, third_text );
  1856.     } else {
  1857.         sprintf( operands, dir_fmt[dir], mem_text, reg_text, third_text );
  1858.     }
  1859.  
  1860.     adjust_assumes();
  1861.     instr_opcode( opcode );
  1862.     instr_operand( operands );
  1863.  
  1864.     return( 2+additional );
  1865. }
  1866.  
  1867. int esc( byte, text, class )
  1868.     uchar   byte;
  1869.     char            *text;
  1870.     int             class;
  1871. {
  1872.     int             size;
  1873.     int             dir;
  1874.     int             type;
  1875.     dword   mod_reg;
  1876.     uchar   mod;
  1877.     uchar   r_m;
  1878.     uchar   lll;        /* Described as LLL in 80386 Prog Ref Man. */
  1879.     uchar   ttt;        /* Described as TTT in 80386 Prog Ref Man. */
  1880.     uchar   esc_byte;
  1881.     uchar   mf;
  1882.     int             additional;
  1883.     int             size_needed;
  1884.     char            line[50];
  1885.     char            temp[50];
  1886.     int             ref_mode;
  1887.  
  1888.     text = text;               /* Prevent unused variable warnings */
  1889.     class=class;              /* Prevent unused variable warnings */
  1890.  
  1891.     size = (byte & 0x01);
  1892.     dir  = (byte & 0x02) >> 1;
  1893.     ref_mode = 0;
  1894.  
  1895.     if ( get_checkc( &mod_reg ) ) {
  1896.         return( 0 );
  1897.     }
  1898.     mod = (uchar)(((int)mod_reg & 0xC0) >> 6);
  1899.     lll = (uchar)(((int)mod_reg & 0x38) >> 3);
  1900.     r_m = (uchar)(((int)mod_reg & 0x07) >> 0);
  1901.  
  1902.     ttt = (uchar)(byte & 0x07);
  1903.     esc_byte = (uchar)(ttt << 3) + lll;
  1904.  
  1905.     if ( mod == 0x03 ) {
  1906.         esc_special( temp, line, esc_byte, r_m );
  1907.         additional = 0;
  1908.     } else {
  1909.         mf = (uchar)((esc_byte & 0x30) >> 4);
  1910.  
  1911.         size_needed = TRUE;
  1912.  
  1913.         switch( mf ) {
  1914.             case 0:     type = DWORD_PTR;   break;
  1915.             case 1:     type = DWORD_PTR;   break;
  1916.             case 2:     type = QWORD_PTR;   break;
  1917.             case 3:     type = WORD_PTR;    break;
  1918.         }
  1919.  
  1920.         /*
  1921.         ** There are always exceptions to the rule (Thank you, Intel)
  1922.         */
  1923.         if (    esc_byte == 0x1D || esc_byte == 0x1F 
  1924.              || esc_byte == 0x3C || esc_byte == 0x3E ) {
  1925.             type = TBYTE_PTR;
  1926.         }
  1927.         if ( esc_byte == 0x2F ) {
  1928.             type = WORD_PTR;
  1929.         }
  1930.         if ( esc_byte == 0x3D || esc_byte == 0x3F ) {
  1931.             type = DWORD_PTR;
  1932.         }
  1933.  
  1934.         if (    (esc_byte >= 0x0C && esc_byte <= 0x0F)
  1935.              || (esc_byte >= 0x2C && esc_byte <= 0x2E) ) {
  1936.             size_needed = FALSE;
  1937.         }
  1938.         sprintf( line, "" );
  1939.         additional = do_mod_rm( line, mod, r_m, type, size_needed, ref_mode );
  1940.         if ( additional == -1 ) {           /* Error in 'do_mod_rm' */
  1941.             return( 0 );
  1942.         }
  1943.         strcpy( temp, esc_inst[esc_byte] );
  1944.     }
  1945.     if ( strlen( temp ) ) {
  1946.         if ( temp[1] == 'n' && fp_wait ) {
  1947.             fp_opcode[0] = temp[0];             /* Remove the 'n' */
  1948.             strcpy( &fp_opcode[1], &temp[2] );
  1949.         } else {
  1950.             strcpy( fp_opcode, temp );
  1951.         }
  1952.         instr_opcode( fp_opcode );
  1953.         instr_operand( line );
  1954.     } else {
  1955.         sprintf( line, "0%02Xh,%s", esc_byte, regs[1][r_m] );
  1956.         instr_opcode( "esc" );
  1957.         instr_operand( line );
  1958.     }
  1959.  
  1960.     fp_wait = FALSE;                /* Reset always */
  1961.     dir = dir;
  1962.     size = size;
  1963.     return( 2+additional );
  1964. }
  1965.